#include "horn-common.h"

/* From Paul Hilfinger */
/** Standard constructors used to connect TYPE to the node-factory
 *  machinery.  SUPERTYPE is the immediate base type of TYPE. */
#define STD_BASE_CONSTRUCTORS(Type, Supertype)				     \
protected:								     \
									     \
    Type (S_Node* oper, size_t n) : Supertype (oper, n) {		     \
    }									     \
									     \
    Type (int syntax) : Supertype (syntax) { }
									    
/** As for STD_BASE_CONSTRUCTORS, but appends trailing ctor-initializers
 *  to constructors. */
#define STD_BASE_CONSTRUCTORS_INIT(Type, Supertype, ...)		     \
protected:								     \
    Type (S_Node* oper, size_t n) : Supertype (oper, n), __VA_ARGS__ {     \
    }									     \
									     \
    Type (int syntax) : Supertype (syntax), __VA_ARGS__ { }

/** Standard constructors, factory method, and exemplar used to
 *  connect TYPE to the node-factory machinery.  SUPERTYPE
 *  the immediate base type of TYPE. */
#define STD_CONSTRUCTORS(Type, Supertype)				     \
    STD_BASE_CONSTRUCTORS (Type, Supertype)				     \
									     \
    Type* make (S_Node* oper, size_t n) {				     \
	return new Type (oper, n);					     \
    }									     \
									     \
    static const Type exemplar

/** As for STD_CONSTRUCTORS, but appends trailing ctor-initializers
 *  to constructors. */
#define STD_CONSTRUCTORS_INIT(Type, Supertype, ...)			     \
protected:								     \
       STD_BASE_CONSTRUCTORS_INIT (Type, Supertype, __VA_ARGS__)	     \
									     \
    Type* make (S_Node* oper, size_t n) {				     \
	return new Type (oper, n);					     \
    }									     \
									     \
    static const Type exemplar

/** Define the standard exemplar for TYPE, registering it with
 *  SYNTAX. */
#define STD_EXEMPLAR(Type, Syntax) const Type Type::exemplar (Syntax)

/* Horn Provided Utilities */
extern bool yyis_known_location (const char* loc);

/* Forward Declarations of Classes */
class S_Node;
class S_Tree;
class S_Token;

class S_Node : public CommonNode<S_Node, S_Token, S_Tree> {
public:
    int line_number ();
        
    virtual void print (std::ostream& out = std::cout, int indent = 0);
    
    const char* ast_op ();
        
    virtual void semantics ();
    
    virtual void* eval ();
    
};

class S_Tree : public CommonTree<S_Node, S_Token, S_Tree> {
public:    
    S_Tree (S_Node* oper, size_t n)
        : CommonTree<S_Node, S_Token, S_Tree>(oper, n)
    { 
        if (oper != NULL && yyis_known_location (oper->loc ()))
            set_loc (oper->loc ());
    }

    S_Tree (int syntax)
        : CommonTree<S_Node, S_Token, S_Tree> (syntax) {}
};

class S_Token : public CommonToken<S_Node, S_Token, S_Tree> {
public:
    S_Token (int syntax, const char* text, size_t len, bool owner = false)
    : CommonToken<S_Node, S_Token, S_Tree> (syntax, text, len, owner) { }
    
    S_Token (int syntax, const std::string& text, bool owner)
    : CommonToken<S_Node, S_Token, S_Tree> (syntax, text, owner) { }
    
    void print (std::ostream& out = std::cout, int indent = 0);
};
